﻿
using PSE.Framework.Communication.Configuration.Adapters.File.FlatFile;
using PSE.Framework.Communication.Adapters.File;
using PSE.Framework.Communication.Configuration.Adapters;
using FileHelpers;
using System;
using System.Collections.Generic;
using System.IO;
using PSE.Framework.Communication.Configuration.File;
using PSE.Framework.Communication.Configuration.File.FlatFile;
using System.Text;
namespace PSE.Framework.Communication.Adapters.File.FlatFile
{
    public class FlatFileOutputAdapter : FileOutputAdapter<FlatFileOutputConfiguration>
    {
        #region Propriedades
        /// <summary>
        /// Dicionario contendo os objetos de traducao de registros
        /// a chave do dicionario sera uma action e o objeto armazenado sera criado de acordo com as
        /// configuracoes informadas na action
        /// </summary>
        private Dictionary<string, ActionDeserializerInfo> _recordInfos;

        private StreamWriter _fileWriter;
        #endregion

        public FlatFileOutputAdapter()
        {
            _recordInfos = new Dictionary<string, ActionDeserializerInfo>();
        }

        protected override void Send(object message)
        {
            if (_fileWriter != null)
            {
                //gravar o registro no arquivo
                _fileWriter.WriteLine((string)message);
            }
        }

        protected override object Serialize(object message, string action)
        {
            //se o registro for uma string, retornar sem qualquer transformacao
            if (message is string)
            {
                return message;
            }
            //se for um objeto
            else
            {
                ActionDeserializerInfo adi = _recordInfos[action];

                //se foi configurada uma forma de transformar o dados bruto em objeto, transformar e retornar
                if (adi.RecordInfo != null)
                {
                    //se foi informado um tipo fixo com a formatacao
                    if (adi.IsFixedType)
                    {
                        return adi.RecordInfo.RecordToString(message);
                    }
                    //se foi informado um arquivo com a formatacao
                    else
                    {
                        return adi.RecordInfo.DictionaryToString(message);
                    }
                }
                //se ainda nao ha um recordInfo, ou seja n ha um arquivo de formato, criar um record info de
                //acordo com o tipo do objeto
                else
                {
                    adi.RecordInfo = new FileHelpers.RecordInfo(message.GetType());
                    adi.IsFixedType = true;
                    return adi.RecordInfo.RecordToString(message);
                }
            }
        }

        protected override void CreateAndOpenFile(string fullPath)
        {
            //recuperar as actions e criar os recordinfos para transformacao dos registros
            bool fixedType = false;
            Type recordType;
            FileHelpers.RecordInfo recordInfo;

            //varrer as actions e criar os recordInfo
            foreach (FlatFileOutputAdapterActionConfiguration action in this.Configuration.Actions)
            {
                //se ja existe uma configuracao para a action
                if (_recordInfos.ContainsKey(action.Name))
                    continue;

                //se informou um arquivo com o formato
                if (!string.IsNullOrEmpty(action.SerializedMessageFile))
                {
                    fixedType = false;
                    recordType = FileHelpers.RunTime.ClassBuilder.ClassFromXmlFile(action.SerializedMessageFile);
                    recordInfo = new FileHelpers.RecordInfo(recordType);
                }
                else
                {
                    fixedType = false;
                    recordInfo = null;
                }

                ActionDeserializerInfo adi = new ActionDeserializerInfo(fixedType, recordInfo);
                _recordInfos.Add(action.Name, adi);
            }

            _fileWriter = new StreamWriter(fullPath, false, Encoding.GetEncoding(this.Configuration.Encoding));

            //caso haja um header configurado, escrever no começo do arquivo
            if (!string.IsNullOrEmpty(this.Configuration.Header))
            {
                _fileWriter.WriteLine(this.Configuration.Header);
            }
        }

        protected override void CloseFile()
        {
            //caso haja um footer configurado, escrever no final do arquivo
            if (!string.IsNullOrEmpty(this.Configuration.Footer))
            {
                _fileWriter.WriteLine(this.Configuration.Footer);
            }

            _fileWriter.Flush();
            _fileWriter.Close();
            _fileWriter.Dispose();
        }


    }//end FlatFileOutputAdapter

}
